package com.fjeld.middleware.constants;

import org.apache.log4j.Logger;
import sun.rmi.runtime.Log;

import java.io.*;
import java.lang.reflect.Array;
import java.util.*;

/**
 * Created by IntelliJ IDEA.
 * User: fjeld
 * Date: 11/12/2011
 * Time: 11:44
 * <p/>
 * Loads properties from a file and exposes it.
 */
public class PropertiesManager extends Properties
{

    private static final Logger LOGGER = Logger.getLogger(PropertiesManager.class);
    private static final String CONFIG_DIR_NAME = "config", CONFIG_FILE_NAME = "config.xml",
                                CONFIG_FULL_NAME = CONFIG_DIR_NAME + "/" + CONFIG_FILE_NAME, BASE_NAME = ".";
    private static final PropertiesManager PROPERTIES_MANAGER = new PropertiesManager();
    private File BASE_FILE = new File(BASE_NAME);

    private PropertiesManager()
    {
        checkIntegrity();
        FileInputStream fis = null;

        try
        {
            LOGGER.info("Loading properties file: " + CONFIG_FULL_NAME);
            fis = new FileInputStream(CONFIG_FULL_NAME);
            this.loadFromXML(fis);

            LOGGER.info("Loaded properties.");
            LOGGER.info("Listing properties:");
            for (String propertyName : this.stringPropertyNames())
            {
                LOGGER.info("  - Property [" + propertyName + "] = [" + this.getProperty(propertyName) + "]");
            }
        } catch (FileNotFoundException e)
        {
            LOGGER.fatal("Cannot find properties file: " + CONFIG_FULL_NAME, e);
            System.exit(1);
        } catch (InvalidPropertiesFormatException e)
        {
            LOGGER.fatal("Invalid properties format in file: " + CONFIG_FULL_NAME, e);
            System.exit(1);
        } catch (IOException e)
        {
            LOGGER.fatal("IOException when reading properties file: " + CONFIG_FULL_NAME, e);
            System.exit(1);
        }
        LOGGER.info("Properties loading finished OK");
    }

    private void checkIntegrity()
    {
        File config_dir = new File(BASE_NAME + "/" + CONFIG_DIR_NAME);
        if (!config_dir.exists())
        {
            createDir(BASE_FILE, CONFIG_DIR_NAME);
        } else
        {
            LOGGER.info("Found config directory: " + BASE_NAME + "/" + CONFIG_DIR_NAME);
        }

        File file = new File(CONFIG_FULL_NAME);
        if (!file.exists())
        {
            createPropertiesFile();
        }    else
        {
            LOGGER.info("Found config file: " + CONFIG_FULL_NAME);
        }
    }

    private void createDir(File dir, String directory)
    {
        LOGGER.info("Creating directory: " + directory + ", from file " + dir);
        try
        {
            File dirToCreate = new File(dir.getCanonicalPath() + "/" + directory);
            boolean isCreateSuccessful = dirToCreate.mkdir();
            LOGGER.info("Was creation successful: " + isCreateSuccessful);
        } catch (IOException e)
        {
            LOGGER.fatal("Could not create config directory.", e);
            System.exit(1);
        }
    }

    private void createPropertiesFile()
    {
        LOGGER.info("Creating clean properties file: " + CONFIG_FULL_NAME);
        FileOutputStream fos = null;
        try
        {
            fos = new FileOutputStream(CONFIG_FULL_NAME);
            storeToXML(fos, "Application specific configuration");
            fos.close();
        } catch (FileNotFoundException e)
        {
            LOGGER.fatal(e);
            System.exit(1);
        } catch (IOException e)
        {
            LOGGER.fatal(e);
            System.exit(1);
        }
        LOGGER.info("Properties file created.");
    }

    public List<String> getPropertyAsList(String key)
    {
        if (!this.containsKey(key))
        {
            LOGGER.info("Does not contain property key: " + key + ".");
            return new ArrayList<String>();
        }

        String property = this.getProperty(key);
        if (null == property)
        {
            LOGGER.info("Property is NULL.");
            return new ArrayList<String>();
        }

        return Arrays.asList(property.split(","));
    }
    public static PropertiesManager getProperties()
    {
        return PROPERTIES_MANAGER;
    }
}
